package cn.cdahua.basic.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.inject.Inject;

import org.hibernate.ObjectNotFoundException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import cn.cdahua.basic.model.Pager;
import cn.cdahua.basic.model.SystemContext;

@SuppressWarnings("unchecked")
public class BaseDao<T> implements IBaseDao<T> {

	/**
	 * 初始化sessionfactory
	 */
	private SessionFactory sessionFactory;

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	@Inject
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	/**
	 * 创建一个Class的对象来获取泛型的class
	 */
	private Class<?> clz;

	public Class<?> getClz() {
		if (clz == null) {
			// 获取泛型的Class对象
			clz = ((Class<?>) (((ParameterizedType) (this.getClass().getGenericSuperclass()))
					.getActualTypeArguments()[0]));
		}
		return clz;
	}

	/**
	 * 对象添加进数据库
	 */
	@Override
	public T add(T t) {
		getSession().save(t);
		return t;
	}

	/**
	 * 更新对象
	 */
	@Override
	public void update(T t) {
		getSession().update(t);
	}

	/**
	 * 根据id删除对象
	 */
	@Override
	public void delete(int id) {
		try {
			getSession().delete(load(id));
		} catch (ObjectNotFoundException e) {

		}
	}

	/**
	 * 根据id获取对象
	 */
	@Override
	public T load(int id) {
		return (T) getSession().load(getClz(), id);
	}

	/**
	 * 根据hql获取对象
	 */
	public Object queryObject(String hql) {
		return getSession().createQuery(hql).uniqueResult();
	}

	/**
	 * 根据hql查询数据
	 * 
	 * @param hql
	 * @param args
	 *            查询条件
	 * @return
	 */
	public T loadByHql(String hql, Object[] args) {
		Query query = getSession().createQuery(hql);
		if (args != null)
			setParameter(query, args);//设置约束条件
		return (T) query.uniqueResult();
	}

	public T loadByHql(String hql, Object arg) {
		return loadByHql(hql, new Object[] { arg });
	}

	public T loadByHql(String hql) {
		return loadByHql(hql, null);
	}
	
	/**
	 * 设置约束条件
	 * @param query
	 * @param args
	 */
	protected void setParameter(Query query, Object[] args) {
		if (args != null && args.length > 0) {
			for (int i = 0; i < args.length; i++) {
				query.setParameter(i, args[i]);
			}
		}
	}

	/**
	 * 设置分页相关参数
	 * @param query
	 * @param pages
	 */
	protected void setPager(Query query, Pager<T> pages) {
		Integer pageOffset = SystemContext.getOffset();//从ThreadLocal中获取pageoffset
		Integer pageSize = SystemContext.getPageSize();//从ThreadLocal中获取pageSize
		if (pageOffset == null || pageOffset < 0)
			pageOffset = 0;
		if (pageSize == null || pageSize < 0)
			pageSize = 15;
		pages.setOffset(pageOffset);
		pages.setSize(pageSize);
		query.setFirstResult(pageOffset).setMaxResults(pageSize);
	}
/**
 * 设置查询结果的排序方式
 * @param hql
 * @return
 */
	protected String setOrder(String hql) {
		String order = SystemContext.getOrder();
		String sort = SystemContext.getSort();
		if (order != null && !"".equals(order.trim())) {
			hql += " order by " + order;
			if ("desc".equals(sort))
				hql += " desc";
			else
				hql += " asc";
		}
		return hql;
	}
/**
 * 根据hql查询返回结果的条数
 * @param hql
 * @param isHql
 * @return
 */
	protected String getCountHql(String hql, boolean isHql) {
		String e = hql.substring(hql.indexOf("from"));//截取from之后的字符串
		String c = "select count(*) " + e;
		if (isHql)
			c = c.replaceAll("fetch", "");//count(*)不支持fetch
		return c;
	}

	/**
	 * 通过hql查询对象
	 * 
	 * @param hql
	 * @param args
	 * @return
	 */
	public List<T> list(String hql, Object[] args) {
		hql = setOrder(hql);
		Query query = getSession().createQuery(hql);
		setParameter(query, args);
		return query.list();
	}

	public List<T> list(String hql, Object arg) {
		return list(hql, new Object[] { arg });
	}

	public List<T> list(String hql) {
		return list(hql, null);
	}
/**
 * 分页查询
 * @param hql
 * @param args
 * @return
 */
	public Pager<T> find(String hql, Object[] args) {
		String cq = getCountHql(hql, true);
		hql = setOrder(hql);
		Query query = getSession().createQuery(hql);
		Query cquery = getSession().createQuery(cq);
		setParameter(query, args);
		setParameter(cquery, args);
		Pager<T> pages = new Pager<T>();
		setPager(query, pages);
		pages.setTotal((long) cquery.uniqueResult());
		pages.setDatas(query.list());
		return pages;
	}

	public Pager<T> find(String hql, Object arg) {
		return find(hql, new Object[] { arg });
	}

	public Pager<T> find(String hql) {
		return find(hql, null);
	}

	public void updateByHql(String hql, Object[] args) {
		Query query = getSession().createQuery(hql);
		setParameter(query, args);
		query.executeUpdate();
	}

	public void updateByHql(String hql, Object arg) {
		updateByHql(hql, new Object[] { arg });
	}

	public void updateByHql(String hql) {
		updateByHql(hql, null);
	}

}
